home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part2 / 11371 < prev    next >
Encoding:
Text File  |  1996-08-05  |  2.8 KB  |  92 lines

  1. Path: vixen.cso.uiuc.edu!usenet
  2. From: homer@uiuc.edu
  3. Newsgroups: comp.lang.c++
  4. Subject: Re: Virtual Base Class
  5. Date: 14 Mar 1996 05:43:54 GMT
  6. Organization: University of Illinois at Urbana
  7. Message-ID: <4i8bmq$qu0@vixen.cso.uiuc.edu>
  8. References: <313F98D0.102E@ucla.edu> <4i1k92$3n8@apoll.informatik.uni-bonn.de> <31472DB0.511A@ucla.edu>
  9. Reply-To: n-dade@uiuc.edu
  10. NNTP-Posting-Host: homer.apr.uiuc.edu
  11. X-Newsreader: IBM NewsReader/2 v1.2
  12.  
  13.  
  14. schregle@Mars (Roland Schregle) suggests this flithy code:
  15.  
  16. >void f()
  17. >{
  18. >   a a1;
  19. >   d* testy = new d; // :)
  20. >   int offset = (void*)testy - (void*)(a*)testy;
  21. >   delete testy;
  22. >   d* pd = (d*)((void*)a1 + offset);
  23. >}
  24.  
  25. Yes that will do the trick, and yes it is filthy!
  26. I have a slightly (only slightly) more elegant solution
  27. to this problem. 
  28.  
  29. My trick is to use a virtual function that returns the
  30. this pointer in each final derived class. That way once
  31. I know that my A* is really a D* I can cast the output
  32. that function to D*. I often make that function protected
  33. and add conversion operators in the base class so that
  34. I cannot forget and convert the void* returned by that
  35. function to any old class*.
  36.  
  37. If you don't feel safe with the operator (since it does
  38. allow automatic conversion from A to D*) you can replace
  39. the operator with a named function.
  40.  
  41. Here's a little example:
  42.  
  43.  
  44. #include <iostream.h>
  45.  
  46. class D;
  47.  
  48. class A {
  49.    protected:
  50.       virtual void* QueryThis() = 0; // returns void* to
  51.                                      // avoid any automatic
  52.                                      // conversions by the
  53.                                      // compiler; is not
  54.                                      // "const" so I don't
  55.                                      // have to return
  56.                                      // "const void*"
  57.    public:
  58.       // I wish I could use this to convert A to D& but
  59.       // the compiler does choke on that. So I convert
  60.       // A to D* instead.
  61.       operator D* () { return (D*) QueryThis(); }
  62. };
  63.  
  64. class B : virtual public A {};
  65. class C : virtual public A {};
  66.  
  67. class D : public B, public C {
  68.    private:
  69.       int i;
  70.    protected:
  71.       void* QueryThis() { return this; } // fill out virtual
  72.                                          // function in final
  73.                                          // derived class so
  74.                                          // that (D*) operator
  75.                                          // in A can get the
  76.                                          // value of D::this
  77.    public:
  78.       D(int ii) : i(ii) {}
  79.       void sayhi() const { cout << "Hi, I'm #" << i << endl; }
  80. };
  81.  
  82. main() {
  83.    D d(12345);       // create a D
  84.    A* a = &d;        // get a pointer to its base class A
  85.    D* p = *a;        // convert the A back to a D*
  86.    p->sayhi();       // a test to see if the pointer is any good
  87.  
  88.    return 0;
  89. }
  90.  
  91.  
  92.